// SPDX-License-Identifier: GPL-2.0
/*
 * RECLAIM: Reclaim An Inused Anonymous Page
 *
 * (C) 2024.03.24 BuddyZhang1 <buddy.zhang@aliyun.com>
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <malloc.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#define DEV_PATH		"/dev/BiscuitOS-RECLAIM"
#define errExit(msg)		do { perror(msg); exit(EXIT_FAILURE); } \
				     while (0)
#define BISCUITOS_IO		0xBD
#define BS_RECLAIM		_IO(BISCUITOS_IO, 0x00)
#define BS_RECLAIM_PREPARE	_IO(BISCUITOS_IO, 0x01)
#define MAP_VADDR		0x6000000000
#define MAP_SIZE		0x1000

int main()
{
	char *base;
	int fd;

	/* OPEN FILE */
	fd  = open(DEV_PATH, O_RDWR);
	if (fd < 0)
		errExit("Open FILE failed");

	/* USE MEMORY */
	base = (char *)mmap(NULL, MAP_SIZE,
			    PROT_READ | PROT_WRITE,
			    MAP_ANONYMOUS | MAP_PRIVATE,
			    -1,
			    0);
	if (base == MAP_FAILED)
		errExit("MMAP Failed");

	/* Write OPS, Trigger #PF */
	*base = 'B';

	/* MARK PAGE LATEST UNUSED */
	ioctl(fd, BS_RECLAIM_PREPARE, (unsigned long)base);

	/* RECLAIM */
	ioctl(fd, BS_RECLAIM, (unsigned long)base);

	/* Re-USE, Trigger #PF */
	BiscuitOS_memory_fluid_enable();
	*base = 'C';
	BiscuitOS_memory_fluid_disable(); // do_user_addr_fault

	munmap(base, MAP_SIZE);
	close(fd);
	return 0;
}
